/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package test.shanika;

import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.FrameGrabber.Exception;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import com.googlecode.javacv.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import objectExtraction.HSVSkinDetector;

public class CalculateHull implements Runnable {

    CanvasFrame canvas = new CanvasFrame("Web Cam Live");
    CanvasFrame canvas1 = new CanvasFrame("HSV Skin");
    //   CanvasFrame canvas2 = new CanvasFrame("YCrCb Skin");
    CanvasFrame canvas3 = new CanvasFrame("Contours");
    CvScalar rgba_min = cvScalar(124, 133, 18, 0);
    CvScalar rgba_max = cvScalar(184, 193, 80, 0);
    CvScalar hsv_min = cvScalar(0, 45, 0, 0);
    CvScalar hsv_max = cvScalar(20, 255, 255, 0);
    CvScalar ycc_min = cvScalar(0, 131, 80, 0);
    CvScalar ycc_max = cvScalar(255, 185, 135, 0);
    //AdaptiveSkinDetector2 adapSkin=new AdaptiveSkinDetector(1,2):
    CvMemStorage storage = CvMemStorage.create();
    CvMemStorage storage1 = CvMemStorage.create();
    CvSeq hull;
    CvSeq fileredHull;
    CvSeq defects;
    IplImage image;
    HSVSkinDetector hs = new HSVSkinDetector();
    TestingWindows tw = new TestingWindows();
    ImageIcon ic;
    CvSize imSize = new CvSize(325, 278);

    public CalculateHull() {

        canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);

    }

    public void run() {
        tw.show();
        FrameGrabber grabber = new OpenCVFrameGrabber("resources/fypVid1.avi");
        //FrameGrabber grabber = new VideoInputFrameGrabber(0);
        try {

            grabber.start();
            Thread.sleep(1000);
            IplImage img;
            img = grabber.grab();

            IplImage hsvSkin = hs.getHSVSkin(img);
            extractContours(hsvSkin, img);
            canvas3.showImage(img);

            //Thread.sleep(10000);
            while (true) {
                img = grabber.grab();

                if (img != null) {
                    //   cvFlip(img, img, 0);
//                    canvas.showImage(img);
                    hsvSkin = hs.getHSVSkin(img);


                    IplImage hsha = cvCloneImage(hsvSkin);
//                    canvas1.showImage(hsvSkin);
                    extractContours(hsvSkin, img);
                    canvas3.showImage(img);
                    //  cvReleaseImage(img);

                    //this.showImages(img, hsha);
                    cvReleaseImage(hsvSkin);
                    cvReleaseImage(hsha);

                }
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(CalculateHull.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception e) {
            try {
                grabber.stop();
            } catch (Exception ex) {
                Logger.getLogger(CalculateHull.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    private IplImage getThresholdImage(IplImage orgImg) {
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);
        cvInRangeS(orgImg, rgba_min, rgba_max, imgThreshold);
        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 15);
        return imgThreshold;


    }

    private IplImage getHSVSkin(IplImage orgImg) {
        IplImage imgHSV = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgHSV, CV_BGR2HSV);
        cvInRangeS(imgHSV, hsv_min, hsv_max, imgThreshold);
        cvReleaseImage(imgHSV);
        IplConvKernel rect_12 = cvCreateStructuringElementEx(3, 3, 2, 2, CV_SHAPE_ELLIPSE, null);
        // cvErode(imgThreshold, imgThreshold, rect_12, 1);
        IplConvKernel rect_6 = cvCreateStructuringElementEx(7, 7, 2, 2, CV_SHAPE_ELLIPSE, null);
        cvMorphologyEx(imgThreshold, imgThreshold, image, rect_12, CV_MOP_CLOSE, 1);
        cvMorphologyEx(imgThreshold, imgThreshold, image, rect_6, CV_MOP_OPEN, 1);


//        cvDilate(imgThreshold, imgThreshold, rect_6, 1);

        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 5);

        return imgThreshold;


    }

    private IplImage getYCrCbSkin(IplImage orgImg) {
        IplImage imgYCC = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgYCC, CV_BGR2YCrCb);
        cvInRangeS(imgYCC, ycc_min, ycc_max, imgThreshold);
        //cvDilate(imgThreshold, imgThreshold, null, 1);
        //cvErode(imgThreshold, imgThreshold, null, 1);

        IplConvKernel rect_12 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvErode(imgThreshold, imgThreshold, rect_12, 1);

        IplConvKernel rect_6 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvDilate(imgThreshold, imgThreshold, null, 1);

        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 5);
        return imgThreshold;


    }

    private IplImage getRGBSkin(IplImage orgImg) {
        IplImage imgHSV = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgHSV, CV_BGR2YCrCb);
        cvInRangeS(imgHSV, ycc_min, ycc_max, imgThreshold);
        //cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 15);
        return imgThreshold;

    }

    private void extractContours(IplImage skin, IplImage img) {
        double result1 = 0;
        double largest = 0;
        double secondlargest = 0;
        CvSeq largestcontour = new CvSeq(null);
        CvSeq secondlargestcontour = new CvSeq(null);
        CvSeq contours = new CvSeq(null);

        int a = cvFindContours(skin, storage, contours, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

        if (a != 0) {
            while (contours != null) {
                result1 = contours.total();
                result1 = cvContourArea(contours, CV_WHOLE_SEQ, 0);
                if (result1 > largest) {
                //    secondlargest = largest;
                    largest = result1;
                    largestcontour = contours;
                }
//                if (secondlargest < result1 && largest != result1) {
//                    secondlargest = result1;
//                    secondlargestcontour = contours;
//                }
                contours = contours.h_next();
            }
            
            System.out.println("Largest= " + largest);
//            System.out.println("second Largest= " + secondlargest);

           
            if (largestcontour != null) {

                cvDrawContours(img, largestcontour, CvScalar.MAGENTA, CvScalar.WHITE, -1, 1, CV_FLOODFILL_MASK_ONLY);

                hull = cvConvexHull2(largestcontour, storage, CV_COUNTER_CLOCKWISE, 1);
                largest = 0;
                CvPoint v1 = null;
                for (int i = 0; i < hull.total(); i++) {

                    CvPoint v = new CvPoint(cvGetSeqElem(hull, i));

                    result1 = v.y();
                    if (result1 > largest) {
                        largest = result1;
                        v1 = v;
                    }

                }
                cvDrawCircle(img, v1, 5, CvScalar.GREEN, -1, 8, 0);

                System.out.println(" X value = " + v1.x() + " ; Y value =" + v1.y());
                cvClearSeq(hull);
                cvClearSeq(largestcontour);
            }

            cvClearMemStorage(storage);

        }
    }

    public void showImages(IplImage images, IplImage skinImages) {

        IplImage testIm = cvCreateImage(imSize, images.depth(), images.nChannels());
        IplImage testSkin = cvCreateImage(imSize, skinImages.depth(), skinImages.nChannels());

        tw.setVisible(false);
        cvResize(images, testIm);
        ic = new ImageIcon(testIm.getBufferedImage());
        tw.getLeftCamLabel().setIcon(ic);

        cvResize(skinImages, testSkin);
        ic = new ImageIcon(testSkin.getBufferedImage());
        tw.getLeftSkinLabel().setIcon(ic);
        cvReleaseImage(testIm);
        cvReleaseImage(testSkin);
    }
}


